//
//  HCConsoleLogger.m
//  HCToolBox
//
//  Created by Hotacool on 2019/3/18.
//

#import "HCConsoleLogger.h"

static const NSString *kConsoleQueue = @"HCConsoleLogger.queue";
@implementation HCConsoleLogger {
    dispatch_queue_t _consoleQueue;
    NSMutableArray * _messages;
    NSMutableArray * _newMessagesBuffer;
    NSDate * _lastUpdate;
    HCConsoleLoggerBlk _nextLogBlock;
    BOOL _updateScheduled;
}

- (void)dealloc {
    
}

- (instancetype)init {
    if (self = [super init]) {
        _maxMessages = 1024;
        _updateInterval = 0.3;
        _updateScheduled = NO;
        _consoleQueue = dispatch_queue_create([kConsoleQueue UTF8String], DISPATCH_QUEUE_SERIAL);
        _messages = [NSMutableArray arrayWithCapacity:_maxMessages];
        _newMessagesBuffer = [NSMutableArray array];
    }
    return self;
}

- (void)subscribNext:(HCConsoleLoggerBlk)logBlock {
    _nextLogBlock = logBlock;
}

- (void)clear {
    dispatch_async(_consoleQueue, ^{
        [self->_messages removeAllObjects];
    });
}

- (NSArray<DDLogMessage *> *)logMessages {
    return [_messages copy];
}
#pragma mark - Logger
- (void)logMessage:(DDLogMessage *)logMessage {
    dispatch_async(_consoleQueue, ^{
        [self->_newMessagesBuffer addObject:logMessage];
        [self updateConsoleIfNeeded];
    });
}

- (void)updateConsoleIfNeeded {
    if (_updateScheduled) {
        return;
    }
    NSTimeInterval interval = _updateInterval + (_lastUpdate?_lastUpdate.timeIntervalSinceNow:-_updateInterval);
    if (interval > 0) {
        _updateScheduled = YES;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self updateNextLog];
            self->_updateScheduled = NO;
        });
    } else {
        [self updateNextLog];
    }
    
}

- (void)updateNextLog {
    _lastUpdate = [NSDate date];
    NSMutableArray * temp = [_newMessagesBuffer copy];
    dispatch_async(_consoleQueue, ^{
        NSInteger overflow = self->_messages.count + self->_newMessagesBuffer.count - self.maxMessages;
        if (overflow > 0) {
            [self->_messages removeObjectsInRange:NSMakeRange(0, overflow)];
        }
        [self->_messages addObjectsFromArray:self->_newMessagesBuffer];
        [self->_newMessagesBuffer removeAllObjects];
        if (self->_nextLogBlock) {
            self->_nextLogBlock(temp);
        }
    });
}

@end
